﻿using SharpCopy.Controller;
using SharpCopy.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace SharpCopy
{
    class SharpCopyManager
    {
        #region Private Members

        private KeyboardListener KeyboardListener;
        private ClipboardDataController ClipboardController;
        private ClipboardMonitor ClipboardMonitor;

        private List<Key> AllowedNumKeys;
        private List<Key> AllowedDKeys;

        private List<Key> ListOfKeysDown;
        private Key allowedKeyDown;

        #endregion

        #region ctor

        public SharpCopyManager()
        {
            KeyboardListener = new KeyboardListener();
            KeyboardListener.KeyDown += KeyboardListener_KeyDown;
            KeyboardListener.KeyUp += KeyboardListener_KeyUp;

            ClipboardController = new ClipboardDataController();

            UIPermission clipBoard = new UIPermission(PermissionState.None);
            clipBoard.Clipboard = UIPermissionClipboard.AllClipboard;

            ClipboardMonitor = new ClipboardMonitor();
            ClipboardMonitor.ClipboardChanged += ClipboardMonitor_ClipboardChanged;

            //Key.Cancel is the same as null
            allowedKeyDown = Key.Cancel;
            ListOfKeysDown = new List<Key>();

            AllowedNumKeys = new List<Key>()
	        {
                Key.NumPad0, Key.NumPad1, Key.NumPad2, Key.NumPad3, Key.NumPad4, 
                Key.NumPad5, Key.NumPad6, Key.NumPad7, Key.NumPad8, Key.NumPad9,
	        };

            AllowedDKeys = new List<Key>()
            {
                Key.D0, Key.D1, Key.D2, Key.D3, Key.D4, Key.D5, Key.D6, Key.D7, Key.D8, Key.D9
            };
        }

        #endregion

        #region Windows System Hooked Events

        void ClipboardMonitor_ClipboardChanged(object sender, ClipboardChangedEventArgs e)
        {
            if(allowedKeyDown != Key.Cancel)
            {
                ClipboardController.RegisterClipBoardData(allowedKeyDown, e.DataObject.GetData(DataFormats.Text));
                allowedKeyDown = Key.Cancel;
                ListOfKeysDown.Clear();
            }
        }

        void KeyboardListener_KeyUp(object sender, RawKeyEventArgs args)
        {
            if (ListOfKeysDown.Contains(Key.LeftCtrl) && 
                (ListOfKeysDown.Intersect(AllowedNumKeys).Any() || ListOfKeysDown.Intersect(AllowedDKeys).Any())
                && !ListOfKeysDown.Contains(Key.C) && !ListOfKeysDown.Contains(Key.V))
            {
                ClipboardController.RestoreToClipboard(allowedKeyDown);
                allowedKeyDown = Key.Cancel;
                ListOfKeysDown.Clear();
            }
            
            if (ListOfKeysDown.Contains(args.Key))
                ListOfKeysDown.Remove(args.Key);
        }

        void KeyboardListener_KeyDown(object sender, RawKeyEventArgs args)
        {
            if (!ListOfKeysDown.Contains(args.Key))
            {
                if (AllowedNumKeys.Contains(args.Key) || AllowedDKeys.Contains(args.Key))
                    allowedKeyDown = args.Key;

                ListOfKeysDown.Add(args.Key);
            }
        }

        #endregion
    }
}
